using System;
using System.IO;
using System.Net;
using System.Text;

namespace Savage.DotNetLibrary.ProtocolLibrary
{
    /// <summary>
    /// An object that is designed to simplify web requests.
    /// </summary>
    public class FtpWrapper
    {
        /// <summary>
        /// Instantiates a new instance of the HttpWrapper class for the specified Uri.
        /// NOTE: A new object must be created for each separate request.
        /// </summary>
        /// <param name="uri">The uri target of the web request.</param>
        public FtpWrapper(Uri uri)
        {
            if (uri == null)
                throw new ArgumentNullException("uri");

            _ftpWebRequest = (System.Net.FtpWebRequest)WebRequest.Create(uri);
        }

        private FtpWebRequest _ftpWebRequest;
        /// <summary>
        /// Provides access to the WebRequest object so the client can set any additional properties.
        /// </summary>
        public FtpWebRequest FtpWebRequest
        {
            get { return _ftpWebRequest; }
        }

        private int _bufferLength = 2048;
        public int BufferLength
        {
            get { return _bufferLength; }
            set { _bufferLength = value; }
        }

        public string EncryptAndUpload(byte[] data, string password, byte[] salt)
        {
            return Upload(Savage.DotNetLibrary.ProtocolLibrary.EncryptionWrapper.Encrypt(data, password, salt));
        }

        public string Upload(byte[] data)
        {

            _ftpWebRequest.Method = System.Net.WebRequestMethods.Ftp.UploadFile;

            byte[] buffer = new byte[_bufferLength];
            int contentLength;

            _ftpWebRequest.ContentLength = data.Length;

            System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(data);

            System.IO.Stream stream = _ftpWebRequest.GetRequestStream();
            contentLength = memoryStream.Read(buffer, 0, _bufferLength);

            while (contentLength != 0)
            {
                stream.Write(buffer, 0, contentLength);
                contentLength = memoryStream.Read(buffer, 0, _bufferLength);
            }

            stream.Close();
            memoryStream.Close();

            return SendFtpWebRequest(_ftpWebRequest);
        }

        public byte[] Download()
        {
            _ftpWebRequest.Method = System.Net.WebRequestMethods.Ftp.DownloadFile;
            
            byte[] buffer = new byte[_bufferLength];
            int contentLength = 0;
            MemoryStream ms = new MemoryStream();
            using (FtpWebResponse response = (FtpWebResponse)_ftpWebRequest.GetResponse())
            {
                using (Stream reader = response.GetResponseStream())
                {
                    contentLength = reader.Read(buffer, 0, buffer.Length);
                    while (contentLength != 0)
                    {
                        ms.Write(buffer, 0, contentLength);
                        contentLength= reader.Read(buffer, 0, buffer.Length);
                    }
                    reader.Close();
                }
                response.Close();
            }
            return ms.ToArray();
        }

        public string GetFileContents()
        {
            byte[] data = Download();
            string contents;
            using (System.IO.StreamReader reader = new System.IO.StreamReader(new System.IO.MemoryStream(data)))
            {
                contents = reader.ReadToEnd();
            }
            
            return contents;
        }

        public string DecryptFileContents(string password, byte[] salt)
        {
            byte[] data = Download();
            byte[] clearBytes = Savage.DotNetLibrary.ProtocolLibrary.EncryptionWrapper.Decrypt(data, password, salt);
            string contents;
            using (System.IO.StreamReader reader = new System.IO.StreamReader(new System.IO.MemoryStream(clearBytes)))
            {
                contents = reader.ReadToEnd();
            }

            return contents;
        }

        public static string SendFtpWebRequest(FtpWebRequest ftpWebRequest)
        {
            if (ftpWebRequest == null)
                throw new ArgumentNullException("ftpWebRequest");

            using (FtpWebResponse response = (FtpWebResponse)ftpWebRequest.GetResponse())
            {
                try
                {
                    using (Stream dataStream = response.GetResponseStream())
                    {
                        using (StreamReader reader = new StreamReader(dataStream))
                        {
                           return reader.ReadToEnd();
                        }
                    }
                }
                finally
                {
                    response.Close();
                }
            }
        }
    }
}
